package dt.inlee.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.sql.Blob;
import java.util.Properties;

import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import dt.inlee.common.constant.AttachmentConstant;
import dt.inlee.common.constant.CommonConstant;
import dt.inlee.common.exception.FrameworkException;

/**
 * 附件的上传下载工具类
 * 
 * @author 潘瑞峥
 * @date 2010-12-11
 */
public final class AttachmentUtil {

	/** 系统日志 */
	private static Logger log = Logger.getLogger(AttachmentUtil.class);

	/** 附件根目录 */
	private static String rootDir = null;

	/** 配置文件 */
	private static Properties props = null;

	/** 存放附件的目录(以系统配置目录加今年年份为附件目录) */
	private static File fileDir = null;

	private AttachmentUtil() {
	}

	/**
	 * 读取配置文件
	 */
	public static void exists() {
		try {
			if (BaseUtil.isEmpty(props))
				props = new Properties();
			// 读取配置文件
			props.load(AttachmentUtil.class.getClassLoader().getResourceAsStream(AttachmentConstant.PROPS_CONF_PATH));
			// 读取值
			rootDir = props.getProperty(AttachmentConstant.ATTR_UPLOAD_PATH);
			/* 文件存放目录默认配置在attachment/attachment.properties的attachment.root属性 */
			if (!BaseUtil.isEmpty(rootDir)) {
				// 存放附件的目录
				fileDir = new File(rootDir, DateUtil.dateToString(DateUtil.getDBTime(), CommonConstant.DATE_YEAR));
				// 检查文件路径是否存在
				if (!fileDir.exists())
					// 创建存放文件的路径
					fileDir.mkdirs();
			} else
				log.info("请在[" + AttachmentConstant.PROPS_CONF_PATH + "]文件里[" + AttachmentConstant.ATTR_UPLOAD_PATH
						+ "]属性配置上传文件存放路径");
		} catch (IOException e) {
			log.info(AttachmentUtil.class.getName() + " static IO异常", e);
		} catch (FrameworkException e) {
			log.info(AttachmentUtil.class.getName() + " static FrameworkException异常", e);
		}
	}

	/**
	 * 通过文件名称来构建文件存放在服务器上的绝对路径
	 * 
	 * @param fileName
	 * @return
	 */
	public static String getFilePath(String fileName) {
		// 检验存放附件的目录
		exists();
		if (!BaseUtil.isEmpty(fileDir) && !BaseUtil.isEmpty(fileName)) {
			File file = new File(fileDir, fileName);
			return file.getAbsolutePath();
		}
		return null;
	}

	/**
	 * 上传文件
	 * 
	 * @param userFilePath: 客户端文件的全路径
	 * @param uploadPath: 存放在服务器上文件的全路径
	 */
	public static void upload(String userFilePath, String uploadPath) {
		// 检验存放附件的目录
		exists();
		if (!BaseUtil.isEmpty(userFilePath) && !BaseUtil.isEmpty(uploadPath)) {
			try {
				// 传入的文件流
				InputStream iptStream = new FileInputStream(userFilePath);
				// 保存的文件流
				OutputStream optStream = new FileOutputStream(uploadPath);
				byte[] buffer_size = new byte[AttachmentConstant.BUFFER_SIZE];
				int size = 0;
				while ((size = iptStream.read(buffer_size)) > 0)
					optStream.write(buffer_size, 0, size);
				// 关闭流
				if (!BaseUtil.isEmpty(iptStream))
					iptStream.close();
				if (!BaseUtil.isEmpty(optStream))
					optStream.close();
			} catch (Exception ex) {
				log.info(AttachmentUtil.class.getName() + ": static void upload(..)异常", ex);
			}
		}
	}

	/**
	 * 下载文件
	 * 
	 * @param filePath
	 * @param fileName
	 * @throws FrameworkException
	 * @throws Exception
	 */
	public static void download(String filePath, String fileName) throws FrameworkException, Exception {
		if (!BaseUtil.isEmpty(filePath) && !BaseUtil.isEmpty(fileName)) {
			// 转换为当前浏览器支持的中文类型的文件名
			fileName = getEncodeFileName(fileName);
			HttpServletResponse response = ServletActionContext.getResponse();
			response.setHeader(AttachmentConstant.HEADER, new StringBuffer(AttachmentConstant.OUTPUTSTREAM_DOWN)
					.append(";filename=").append(fileName).toString());
			response.setCharacterEncoding(AttachmentConstant.UTF_ENCODING);
			// 设置缓冲大小
			response.setBufferSize(AttachmentConstant.BUFFER_SIZE);
			response.setContentType(AttachmentConstant.CONTENT_TYPE);
			// 传入的文件流
			InputStream iptStream = new FileInputStream(filePath);
			// 保存的文件流
			OutputStream optStream = response.getOutputStream();
			byte[] buffer_size = new byte[AttachmentConstant.BUFFER_SIZE];
			int size = 0;
			while ((size = iptStream.read(buffer_size)) > 0) {
				optStream.write(buffer_size, 0, size);
			}
			optStream.flush();
			// 关闭流
			if (!BaseUtil.isEmpty(optStream))
				optStream.close();
			if (!BaseUtil.isEmpty(iptStream))
				iptStream.close();
			// 回收下
			System.gc();
		}
	}

	/**
	 * 下载文件
	 * 
	 * @param servletOutputStream
	 * @param fileName
	 * @param blob
	 * @throws FrameworkException
	 * @throws Exception
	 */
	public static void download(String fileName, Blob blob) throws FrameworkException, Exception {
		// 转换为当前浏览器支持的中文类型的文件名
		fileName = getEncodeFileName(fileName);
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setHeader(AttachmentConstant.HEADER, new StringBuffer(AttachmentConstant.OUTPUTSTREAM_DOWN).append(
				";filename=").append(fileName).toString());
		response.setCharacterEncoding(AttachmentConstant.UTF_ENCODING);
		// 设置缓冲大小
		response.setBufferSize(AttachmentConstant.BUFFER_SIZE);
		response.setContentType(AttachmentConstant.CONTENT_TYPE);
		// 传入的文件流
		InputStream iptStream = blob.getBinaryStream();
		// 保存的文件流
		OutputStream optStream = response.getOutputStream();
		byte[] buffer_size = new byte[AttachmentConstant.BUFFER_SIZE];
		int size = 0;
		while ((size = iptStream.read(buffer_size)) > 0) {
			optStream.write(buffer_size, 0, size);
		}
		optStream.flush();
		// 关闭流
		if (!BaseUtil.isEmpty(optStream))
			optStream.close();
		if (!BaseUtil.isEmpty(iptStream))
			iptStream.close();
		// 回收下
		System.gc();

	}

	/**
	 * 通过文件路径删除文件
	 * 
	 * @param filePath
	 * @throws FrameworkException
	 */
	public static void daleteFile(String filePath) throws FrameworkException {
		if (!BaseUtil.isEmpty(filePath)) {
			File file = new File(filePath);
			// 文件存在且为标准文件类型
			if (file.exists() && file.isFile())
				file.delete();
		}
	}

	/**
	 * 处理各种浏览器下载乱码问题
	 * 通过浏览器内核类型，返回浏览器支持的中文
	 * (目前常用内核，个人觉得就这四大类)
	 * 
	 * @param fileName
	 * @return
	 * @throws FrameworkException
	 * @throws Exception
	 */
	public static String getEncodeFileName(String fileName) throws FrameworkException, Exception {
		// 浏览器内核信息
		String userAgent = ServletActionContext.getRequest().getHeader(AttachmentConstant.HEADER_USER_AGENT)
				.toUpperCase();
		if (!BaseUtil.isEmpty(userAgent) && !BaseUtil.isEmpty(fileName)) {
			/* IE */
			if (-1 != userAgent.indexOf(AttachmentConstant.HEADER_BROWSER_MSIE))
				return URLEncoder.encode(fileName, AttachmentConstant.UTF_ENCODING);
			/* Mozilla */
			else if (-1 != userAgent.indexOf(AttachmentConstant.HEADER_BROWSER_MOZILLA))
				return new String(fileName.getBytes(), AttachmentConstant.ISO_ENCODING);
			/* Safari */
			else if (-1 != userAgent.indexOf(AttachmentConstant.HEADER_BROWSER_SAFARI))
				return new String(fileName.getBytes(), AttachmentConstant.ISO_ENCODING);
			/* Opera */
			else if (-1 != userAgent.indexOf(AttachmentConstant.HEADER_BROWSER_OPERA))
				return new String(fileName.getBytes(), AttachmentConstant.ISO_ENCODING);
			/* 其它内核浏览器 */
			else
				return new String(fileName.getBytes(), AttachmentConstant.ISO_ENCODING);
		}
		return fileName;
	}

}